import*as e from"../../../core/platform/platform.js";import*as t from"../../lit-html/lit-html.js";import*as r from"../code_highlighter/code_highlighter.js";import*as n from"../helpers/helpers.js";import*as o from"../render_coordinator/render_coordinator.js";const i=new CSSStyleSheet;function s(e){return"children"in e}i.replaceSync(':host{--list-group-padding:16px}li{border:2px solid transparent;list-style:none;text-overflow:ellipsis;min-height:12px}.compact{border:0}.tree-node-key{white-space:var(--override-key-whitespace-wrapping);min-width:0;flex-grow:1}.arrow-icon{display:block;user-select:none;-webkit-mask-image:var(--image-file-triangle-right);background-color:var(--icon-default);content:"";text-shadow:none;height:14px;width:14px;overflow:hidden;flex:none;transition:transform 200ms}ul{margin:0;padding:0}ul[role="group"]{padding-left:var(--list-group-padding)}li:not(.parent) > .arrow-and-key-wrapper > .arrow-icon{-webkit-mask-size:0}li.parent.expanded > .arrow-and-key-wrapper > .arrow-icon{transform:rotate(90deg)}li.is-top-level{border-top:var(--override-top-node-border)}li.is-top-level:last-child{border-bottom:var(--override-top-node-border)}:host([animated]) li:not(.is-top-level){animation-name:slideIn;animation-duration:150ms;animation-timing-function:cubic-bezier(0,0,0.3,1);animation-fill-mode:forwards}@keyframes slideIn{from{transform:translateY(-5px);opacity:0%}to{transform:none;opacity:100%}}.arrow-and-key-wrapper{display:flex;align-content:center;align-items:center}[role="treeitem"]:focus{outline:0}ul[role="tree"]:focus-within [role="treeitem"].selected > .arrow-and-key-wrapper{background-color:var(--legacy-item-selection-bg-color)}.text-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.inline-icon{vertical-align:sub}@media (forced-colors: active){.arrow-icon{background-color:ButtonText}ul[role="tree"]:focus-within [role="treeitem"].selected{outline:solid 1px ButtonText}}\n/*# sourceURL=treeOutline.css */\n');class d extends t.Directive.Directive{constructor(e){if(super(e),e.type!==t.Directive.PartType.ATTRIBUTE)throw new Error("TrackDOMNodeToTreeNode directive must be used as an attribute.")}update(e,[t,r]){const n=e.element;if(!(n instanceof HTMLLIElement))throw new Error("trackTreeNodeToDOMNode must be used on <li> elements.");t.set(n,r)}render(e,t){}}const a=t.Directive.directive(d),l=e=>{const t=e.parentElement?.parentElement;if(t&&t instanceof HTMLLIElement){const e=t.nextElementSibling;return e&&e instanceof HTMLLIElement?e:l(t)}return null},c=e=>{const t=e.querySelector(':scope > [role="group"] > [role="treeitem"]:first-child');if(!t)throw new Error("Could not find child of expanded node.");return t},h=e=>null!==e.getAttribute("aria-expanded"),p=e=>h(e)&&"true"===e.getAttribute("aria-expanded"),u=e=>{const t=e.querySelector(':scope > [role="group"] > [role="treeitem"]:last-child');if(!t)throw new Error("Could not find child of expanded node.");return p(t)?u(t):t},f=e=>{let t=e.parentElement;if(!t)return null;for(;t&&"treeitem"!==t.getAttribute("role")&&t instanceof HTMLLIElement==!1;)t=t.parentElement;return t},m=new WeakMap,w=async e=>{if(!e.children)throw new Error("Asked for children of node that does not have any children.");const t=m.get(e);if(t)return t;const r=await e.children();return m.set(e,r),r},N=async(e,t)=>{for(const r of e){const e=await g(r,t,[r]);if(null!==e)return e}return null},g=async(e,t,r)=>{if(e.id===t)return r;if(e.children){const n=await w(e);for(const e of n){const n=await g(e,t,[...r,e]);if(null!==n)return n}}return null},v=e=>{const{currentDOMNode:t,currentTreeNode:r,direction:n,setNodeExpandedState:o}=e;if(!r)return t;if("ArrowDown"===n){if(p(t))return c(t);const e=(e=>{const t=e.nextElementSibling;return t&&t instanceof HTMLLIElement?t:null})(t);if(e)return e;const r=l(t);if(r)return r}else{if("ArrowRight"===n)return h(t)?p(t)?c(t):(o(r,!0),t):t;if("ArrowUp"===n){const e=(e=>{const t=e.previousElementSibling;return t&&t instanceof HTMLLIElement?t:null})(t);if(e)return p(e)?u(e):e;const r=f(t);if(r&&r instanceof HTMLLIElement)return r}else if("ArrowLeft"===n){if(p(t))return o(r,!1),t;const e=f(t);if(e&&e instanceof HTMLLIElement)return e}}return t};var T=Object.freeze({__proto__:null,isExpandableNode:s,trackDOMNodeToTreeNode:a,getNodeChildren:w,getPathToTreeNode:N,findNextNodeForTreeOutlineKeyboardNavigation:v});const y=o.RenderCoordinator.RenderCoordinator.instance();class E extends Event{static eventName="itemselected";data;constructor(e){super(E.eventName,{bubbles:!0,composed:!0}),this.data={node:e}}}class x extends Event{static eventName="itemmouseover";data;constructor(e){super(x.eventName,{bubbles:!0,composed:!0}),this.data={node:e}}}class S extends Event{static eventName="itemmouseout";data;constructor(e){super(S.eventName,{bubbles:!0,composed:!0}),this.data={node:e}}}class b extends HTMLElement{static litTagName=t.literal`devtools-tree-outline`;#e=this.attachShadow({mode:"open"});#t=[];#r=new Map;#n=new WeakMap;#o=!1;#i=null;#s=null;#d=(e,r)=>("string"!=typeof e.treeNodeData&&console.warn(`The default TreeOutline renderer simply stringifies its given value. You passed in ${JSON.stringify(e.treeNodeData,null,2)}. Consider providing a different defaultRenderer that can handle nodes of this type.`),t.html`${String(e.treeNodeData)}`);#a;#l=!1;#c=!1;#h=!1;static get observedAttributes(){return["nowrap","toplevelbordercolor"]}attributeChangedCallback(e,t,r){switch(e){case"nowrap":this.#p(r);break;case"toplevelbordercolor":this.#u(r)}}connectedCallback(){this.#u(this.getAttribute("toplevelbordercolor")),this.#p(this.getAttribute("nowrap")),this.#e.adoptedStyleSheets=[i,r.Style.default]}get data(){return{tree:this.#t,defaultRenderer:this.#d}}set data(e){this.#d=e.defaultRenderer,this.#t=e.tree,this.#a=e.filter,this.#l=e.compact||!1,this.#o||(this.#s=this.#t[0]),this.#f()}async expandRecursively(e=2){await Promise.all(this.#t.map((t=>this.#m(t,0,e)))),await this.#f()}async collapseAllNodes(){this.#r.clear(),await this.#f()}async expandToAndSelectTreeNode(e){return this.expandToAndSelectTreeNodeId(e.id)}async expandToAndSelectTreeNodeId(e){const t=await N(this.#t,e);if(null===t)throw new Error(`Could not find node with id ${e} in the tree.`);t.forEach(((e,r)=>{r<t.length-1&&this.#w(e,!0)})),this.#i=e,await this.#f()}expandNodeIds(e){return e.forEach((e=>this.#r.set(e,!0))),this.#f()}focusNodeId(e){return this.#i=e,this.#f()}async collapseChildrenOfNode(e){const t=this.#n.get(e);t&&(await this.#N(t),await this.#f())}#p(e){n.SetCSSProperty.set(this,"--override-key-whitespace-wrapping",null!==e?"nowrap":"initial")}#u(e){n.SetCSSProperty.set(this,"--override-top-node-border",e?`1px solid ${e}`:"")}async#N(e){if(!s(e)||!this.#g(e))return;const t=await this.#v(e),r=Promise.all(t.map((e=>this.#N(e))));await r,this.#w(e,!1)}async#T(e,t){const r=await w(e),n=[];for(const e of r){const r=t(e.treeNodeData),o=this.#y(e)||e.id===this.#i,i=this.#r.get(e.id);if("SHOW"===r||o||i)n.push(e);else if("FLATTEN"===r&&s(e)){const r=await this.#T(e,t);n.push(...r)}}return n}async#v(e){const t=await w(e),r=this.#a;if(!r)return t;const n=await this.#T(e,r);return n.length?n:t}#w(e,t){this.#r.set(e.id,t)}#g(e){return this.#r.get(e.id)||!1}async#m(e,t,r){if(!s(e))return;if(this.#w(e,!0),t===r||!s(e))return;const n=await this.#v(e);await Promise.all(n.map((e=>this.#m(e,t+1,r))))}#E(e){return t=>{t.stopPropagation(),s(e)&&(this.#w(e,!this.#g(e)),this.#f())}}#x(e){e.stopPropagation();const t=null!==this.getAttribute("clickabletitle"),r=e.currentTarget,n=this.#n.get(r);t&&n&&s(n)&&this.#w(n,!this.#g(n)),this.#S(r)}async#S(e){const t=this.#n.get(e);t&&(this.#s=t,await this.#f(),this.dispatchEvent(new E(t)),y.write("DOMNode focus",(()=>{e.focus()})))}#b(e){if("Home"===e){const e=this.#e.querySelector('ul[role="tree"] > li[role="treeitem"]');e&&this.#S(e)}else if("End"===e){const e=this.#e.querySelectorAll('li[role="treeitem"]'),t=e[e.length-1];t&&this.#S(t)}}async#k(e,t){const r=this.#n.get(t);if(!r)return;const n=v({currentDOMNode:t,currentTreeNode:r,direction:e,setNodeExpandedState:(e,t)=>this.#w(e,t)});await this.#S(n)}#C(e){const t=this.#n.get(e);if(t&&s(t)){const e=this.#g(t);this.#w(t,!e),this.#f()}}async#I(t){if(!(t.target instanceof HTMLLIElement))throw new Error("event.target was not an <li> element");"Home"===t.key||"End"===t.key?(t.preventDefault(),this.#b(t.key)):e.KeyboardUtilities.keyIsArrowKey(t.key)?(t.preventDefault(),await this.#k(t.key,t.target)):"Enter"!==t.key&&" "!==t.key||(t.preventDefault(),this.#C(t.target))}#M(e){this.#i=null,this.#S(e)}#y(e){return!!this.#s&&e.id===this.#s.id}#D(e,{depth:r,setSize:o,positionInSet:i}){let d;const l=this.#g(e);if(s(e)&&l){const n=this.#v(e).then((e=>e.map(((t,n)=>this.#D(t,{depth:r+1,setSize:e.length,positionInSet:n})))));d=t.html`<ul role="group">${t.Directives.until(n)}</ul>`}else d=t.nothing;const c=this.#y(e)?0:-1,h=t.Directives.classMap({expanded:s(e)&&l,parent:s(e),selected:this.#y(e),"is-top-level":0===r,compact:this.#l}),p=t.Directives.ifDefined(s(e)?String(l):void 0);let u;return u=e.renderer?e.renderer(e,{isExpanded:l}):this.#d(e,{isExpanded:l}),t.html` <li role="treeitem" tabindex="${c}" aria-setsize="${o}" aria-expanded="${p}" aria-level="${r+1}" aria-posinset="${i+1}" class="${h}" @click="${this.#x}" track-dom-node-to-tree-node="${a(this.#n,e)}" on-render="${n.Directives.nodeRenderedCallback((t=>{t instanceof HTMLLIElement&&this.#i&&e.id===this.#i&&this.#M(t)}))}"> <span class="arrow-and-key-wrapper" @mouseover="${()=>{this.dispatchEvent(new x(e))}}" @mouseout="${()=>{this.dispatchEvent(new S(e))}}"> <span class="arrow-icon" @click="${this.#E(e)}"> </span> <span class="tree-node-key" data-node-key="${e.treeNodeData}">${u}</span> </span> ${d} </li> `}async#f(){if(!this.#c)return this.#c=!0,await y.write("TreeOutline render",(()=>{t.render(t.html` <div class="wrapping-container"> <ul role="tree" @keydown="${this.#I}"> ${this.#t.map(((e,t)=>this.#D(e,{depth:0,setSize:this.#t.length,positionInSet:t})))} </ul> </div> `,this.#e,{host:this})})),this.#o=!0,this.#c=!1,this.#h?(this.#h=!1,this.#f()):void 0;this.#h=!0}}n.CustomElements.defineComponent("devtools-tree-outline",b);var k=Object.freeze({__proto__:null,defaultRenderer:function(e){return t.html`${e.treeNodeData}`},ItemSelectedEvent:E,ItemMouseOverEvent:x,ItemMouseOutEvent:S,TreeOutline:b});export{k as TreeOutline,T as TreeOutlineUtils};
